package seiacpjava_a2.datastructures.hashtable;

import seiacpjava_a2.datastructures.DataStructure;
import seiacpjava_a2.datastructures.linkedlist.LinkedList;

public class HashTable extends DataStructure {

	int size;

	int numberOfBuckets;
	public LinkedList[] buckets;

	HashTableStrategy strategy;

	private void initialize() {
		for (int i = 0; i < numberOfBuckets; i++) {
			buckets[i] = new LinkedList();
		}
	}

	private void build(int[] items) {

		for (int i = 0; i < items.length; i++) {
			this.add(items[i]);
		}
	}

	// private int hash(int item) {
	// int hashIndex = item % numberOfBuckets;
	// return hashIndex;
	// }

	// private int calculateNumberOfBuckets(int maxSize)
	// {
	// return (maxSize <= 100) ? 10: maxSize / 10 ;
	// }
	public HashTable(int[] items, HashTableStrategy strategy) {

		this.strategy = strategy;
		// this.numberOfBuckets = this.calculateNumberOfBuckets(items.length);
		this.numberOfBuckets = this.strategy.calculateNumberOfBuckets(items);
		this.buckets = new LinkedList[this.numberOfBuckets];
		this.initialize();
		this.build(items);
	}

	public void add(int item) {

		int hashIndex = this.strategy.hash(item);
		LinkedList bucket = buckets[hashIndex];
		
		
		if (!bucket.contains(item)) {
			buckets[hashIndex].add(item);
			++(this.size);
		}
	}

	public boolean contains(int item) {
		int hashIndex = this.strategy.hash(item);
		
		if ( hashIndex >= this.numberOfBuckets)
		{
			this.numberOfAccesses = 0;
			return false;
		}
		
		LinkedList bucket = buckets[hashIndex];
		if (bucket.contains(item)) {
			this.numberOfAccesses = bucket.getNumberOfAccesses();
			return true;
		}
		this.numberOfAccesses = bucket.getNumberOfAccesses();
		return false;
	}

	int getNumberOfBuckets() {
		return numberOfBuckets;
	}

	 
	 @Override
	public String getDatatStructureName() {
		return "HashTable";
	}
	

	LinkedList getBucket(int index) {
		return this.buckets[index];
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public String toString()
	{
		StringBuffer out = new StringBuffer();
		
		String EOL = "\r\n";		
		String line = "==================================================================================" + EOL;
		String title = "Hashtable" + EOL;
		String size = " Number of Items: " + this.size;
		
		out.append(line);
		out.append(title);
		out.append(size);
		
		for (int i = 0 ; i < this.numberOfBuckets; i++)
		{
			LinkedList bucket = this.buckets[i];
			out.append("bucket" + i + "|");
			for (int j =0 ; j < bucket.getLength(); j++){
				if ( j <= bucket.getLength() - 1){
				out.append(bucket.getItemAt(j) + ",");
				}else
				{
					out.append(bucket.getItemAt(j) + EOL);
				}
			}
		}
		
		out.append(line);
		return out.toString();
	}
}
